package bdhub.littletail.lib.net.request;

import android.util.Config;
import android.util.Log;

import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;

import org.apache.http.protocol.HTTP;

import java.io.File;
import java.io.UnsupportedEncodingException;

import bdhub.littletail.lib.config.CConfig;
import bdhub.littletail.app.config.NetworkConfig;
import bdhub.littletail.app.utils.FileNameGenerator;
import bdhub.littletail.app.utils.Md5FileNameGenerator;
import bdhub.littletail.lib.net.listener.OnResponseListener;
import bdhub.littletail.lib.net.volley.BusinessError;
import bdhub.littletail.lib.net.volley.NetworkResponse;
import bdhub.littletail.lib.net.volley.ParseError;
import bdhub.littletail.lib.net.volley.Request;
import bdhub.littletail.lib.net.volley.Response;
import bdhub.littletail.lib.utils.FileUtils;
import bdhub.littletail.lib.utils.StringUtil;

/**
 * Created by Freddy on 2016/2/23.
 * chenshichao@outlook.com
 */
public class JsonRequest extends CustomRequest<JSONObject> {

    /**
     * MD5文件名称生成工具
     */
    private static final FileNameGenerator FILE_NAME_GENERATOR = new Md5FileNameGenerator();

    private final String TAG = JsonRequest.class.getSimpleName();
    /**
     * 接口地址
     */
    private String mFunction;

    /**
     * 是否应该缓存
     */
    private boolean mShouldCache;

    /**
     * 缓存数据
     */
    private String mCacheResponse;

    /**
     * 网络请求回调类
     */
    private final OnResponseListener<JSONObject> mOnResponseListener;

    public JsonRequest(String function, OnResponseListener<JSONObject> listener) {
        this(function, null, listener);
    }

    /**
     * 创建 JSON 请求
     * @param function 接口地址
     * @param params 任意可以转换为 JsonString 的对象 (如：JavaBean,List<JavaBean>,List<String>,List<Map<String,Object>)
     * @param listener 网络请求回调类
     */
    public JsonRequest(String function, Object params, OnResponseListener<JSONObject> listener) {
        super(function, params, listener);
        this.mFunction = function;
        this.mOnResponseListener = listener;
    }

    @Override
    public Request<?> setShouldCache(boolean shouldCache) {
        if(mShouldCache) {
            Log.v(TAG, "try to load cache：" + mFunction);
            try {
                File file = getCacheFile();
                // 如果存在缓存文件，则读取
                if(file.exists() && file.length() > 0) {
                    String cacheString = FileUtils.readFile(file.getAbsolutePath());
                    JSONObject response = JSONObject.parseObject(cacheString);
                    Log.v(TAG, "命中网络缓存：" + mFunction);
                    Log.v(TAG, "cache loaded：" + mFunction);
                    mOnResponseListener.onCacheLoaded(response);
                    Log.v(TAG, "cache call back：" + mFunction);
                    mCacheResponse = cacheString;
                }else {
                    mOnResponseListener.onNoCache();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            this.mShouldCache = shouldCache;
        }
        return this;
    }

    @Override
    protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
        String jsonString;
        try {
            jsonString = new String(response.data, HTTP.UTF_8);
        } catch (UnsupportedEncodingException e) {
            return Response.error(new ParseError(e));
        }

        if(Config.DEBUG) {
            Log.i(TAG, "HTTP JSON Response：" + jsonString);
        }

        JSONObject jsonObject;
        try {
            jsonObject = JSONObject.parseObject(jsonString);
        } catch (JSONException e) {
            // 返回的不是json数据，很可能是服务器的接口报错了
            return Response.error(new ParseError(e));
        }

        if(0 == jsonObject.getIntValue(NetworkConfig.PARAM_COMMON_ERROR_CODE)) {
            jsonString = jsonObject.getString(NetworkConfig.PARAM_COMMON_RESPONSE_DATA);
            // 如果返回的内容没有更新，则不继续处理了
            if(mShouldCache && jsonString.equals(mCacheResponse)) {
                mCacheResponse = null;
                Log.v(TAG, "网络请求返回的内容与缓存一致：" + mFunction);
                cancel();
                mOnResponseListener.onFinished();
                return null;
            }

            mCacheResponse = null;
            return Response.success(JSONObject.parseObject(jsonString), null);
        }else {
            BusinessError networkError = new BusinessError();
            networkError.setErrorCode(jsonObject.getIntValue(NetworkConfig.PARAM_COMMON_ERROR_CODE));
            networkError.setMessage(jsonObject.getString(NetworkConfig.PARAM_COMMON_ERROR_MESSAGE));
            jsonString = jsonObject.getString(NetworkConfig.PARAM_COMMON_RESPONSE_DATA);
            if (!StringUtil.isEmpty(jsonString)) {
                networkError.setData(JSONObject.parseObject(jsonString));
            }
            return Response.error(networkError);
        }
    }

    @Override
    protected void deliverResponse(JSONObject response) {
        super.deliverResponse(response);
        try {
            String responseString = response.toJSONString();
            FileUtils.writeFile(getCacheFile().getAbsolutePath(), responseString);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取缓存文件
     * @return
     */
    private File getCacheFile() {
        File cacheFolder = FileUtils.getCacheFolder(CConfig.NETWORK_CHACHE_FOLDER);
        String fileName = FILE_NAME_GENERATOR.generate(mFunction);
        File file = new File(cacheFolder.getAbsolutePath() + File.separator + fileName);
        return file;
    }
}
